package com.xyy.saas.payment.adpater.unionpay;

import com.alibaba.fastjson.JSON;
import com.unionpay.acp.sdk.SDKConfig;
import com.unionpay.acp.sdk.SDKUtil;
import com.unionpay.acp.sdksample.multicert.DemoBase;
import com.xyy.saas.payment.common.exception.PaymentException;
import com.xyy.saas.payment.cores.bo.PayBo;
import com.xyy.saas.payment.cores.enums.PayModeEnum;
import com.xyy.saas.payment.cores.enums.ResultCodeEnum;
import com.xyy.saas.payment.cores.vo.UnionPayConfigVo;
import com.xyy.saas.payment.payment.core.dto.PayDto;
import com.xyy.saas.payment.payment.core.dto.RefundDto;
import com.xyy.saas.payment.util.ApolloUtil;
import com.xyy.saas.payment.util.DateUtil;
import com.xyy.saas.payment.util.UnionPayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Map;
import java.util.SortedMap;

/**
 * @author niuhaiyu
 * @ClassName UnionPayOnlineGwHanlder
 * @Description 描述
 * @Date 2021/6/29 下午3:01
 */
@Component
public class UnionPayAppWapHanlder extends AbstractUnionPayChannelHandler{
    private static final Logger LOGGER = LoggerFactory.getLogger(UnionPayAppWapHanlder.class);

    @Override
    public String getMethod() {
        return PayModeEnum.APP_WAP.getMode();
    }

    @Override
    public PayBo pay(PayDto payDto) throws PaymentException {
        PayBo payBo = null;
        try {
            LOGGER.info("UnionPayAppWapHanlder pay begin payDto:{}", JSON.toJSONString(payDto));
            PayBo appPayBo = redisClient.get(payDto.getPayMode() + payDto.getPayNo() + payDto.getChannel(), PayBo.class);
            if (appPayBo != null) {
                LOGGER.info("UnionPayAppWapHanlder pay end get from redis appPayBo:{}", JSON.toJSONString(appPayBo));
                return appPayBo;
            }

            UnionPayConfigVo unionPayConfigVo = channelSettingManager.getUnionPayConfig(payDto.getBusinessOrderType(), payDto.getPayMode());

            if (unionPayConfigVo == null) {
                throw new PaymentException(ResultCodeEnum.UNIONPAY_CONFIG_NOT_EXITS);
            }

            unionPayUtils.init(unionPayConfigVo);
            SortedMap params = joinPayRequestData(payDto);
            //生成签名
            Map<String, String> signMap = unionPayUtils.signData(params);
            Map<String, String> resultMap = unionPayUtils.post(SDKConfig.getConfig().getAppRequestUrl(), signMap);
            LOGGER.info("UnionPayAppWapHanlder invoke unionpay result:{}", JSON.toJSONString(resultMap));
            String sbHtml = "";
            if (SDKUtil.validate(resultMap, DemoBase.encoding)){
                sbHtml = resultMap.get("tn");
            }
            payBo = new PayBo();
            payBo.setPayLoad(sbHtml);
            payBo.setPayNO(payDto.getPayNo());
            LOGGER.info("UnionPayAppWapHanlder pay result:{}", JSON.toJSONString(payBo));
            return payBo;

        }catch (PaymentException e){
            LOGGER.error("UnionPayAppWapHanlder pay error payDto:{}", JSON.toJSON(payDto), e);
            payBo = null;
            throw e;
        }
        catch (Exception e) {
            LOGGER.error("UnionPayAppWapHanlder pay error payDto:{}", JSON.toJSON(payDto), e);
            payBo = null;
            throw new PaymentException(ResultCodeEnum.DEFAULT_ERROR);
        } finally {
            if(payBo != null){
                //默认超时时间,如果业务有传超时时间就按照他们的时间+5400秒
                Integer expire = 5400;
                if (null != payDto.getTimeExpire() && payDto.getTimeExpire().after(new Date())) {
                    expire = DateUtil.getSecondsFromToday(payDto.getTimeExpire()).intValue() + expire;
                }
                redisClient.set(payDto.getPayMode() + payDto.getPayNo() + payDto.getChannel(), payBo, expire);
            }

        }
    }

    @Override
    public SortedMap joinRefundRequestData(RefundDto refundDto) {
        SortedMap paramsMap = unionPayUtils.joinRefundRequestData(refundDto);
        //渠道类型，这个字段区分B2C网关支付和手机wap支付；07：PC,平板  08：手机
        paramsMap.put("channelType", "08");
        //商户退款单号
        paramsMap.put("orderId", refundDto.getRefundNo());
        //原交易查询流水号
        paramsMap.put("origQryId", refundDto.getChannelChargeId());
        //订单发送时间
        paramsMap.put("txnTime", DateUtil.currentTimestamp2String(DateUtil.YYYYMMDDHHMMSS));
        //交易金额，消费撤销时需和原消费一致
        paramsMap.put("txnAmt", String.valueOf(refundDto.getAmount()));
        //请求方保留域
        paramsMap.put("reqReserved", "08");
        return paramsMap;
    }

    @Override
    public SortedMap joinPayRequestData(PayDto payDto) {
        SortedMap params = unionPayUtils.joinPayRequestData(payDto);

        //渠道类型，这个字段区分B2C网关支付和手机wap支付；07：PC,平板  08：手机
        params.put("channelType", "08");

        String url = ApolloUtil.getProperty(UnionPayUtils.UNIONPAY_BACK_PAY_NOTIFY_URL);

        //后台通知地址
        params.put("backUrl", url);
        //前台通知地址
        params.put("frontUrl", DemoBase.frontUrl);
        params.put("reqReserved", "08");

        return params;
    }
}
